using System;
using System.Diagnostics;
using System.Linq;
using Mbs.Messaging;
using Mbs.Modularity.AddIns;
using Mbs.Reflection;

namespace Mbs.Modularity
{
    [Serializable]
    [DebuggerDisplay("First={First}, Id={Meta.Id},State={State}")]
    public class Module :  MarshalByRefObject, IModule
    {
        public ModuleState State { get; protected set; }
        public int Id { get; private set; }
        public IModuleMeta Meta { get; private set; }
        
        private IMessageBus MessageBus;
        private IModuleActivatorProcessor ModuleActivatorProcessor;
        private IAddInTree AddInTree;
        private IModuleListner Listner = ModuleListnerManager.Listner;

        private static int counter = 0;


        public Module(IModuleMeta meta)
        {
            counter++;
            Id = counter;

            Meta = meta;
            State = ModuleState.Installed;

            MessageBus = ServiceLocator.Current.Get<IMessageBus>();
            AddInTree = ServiceLocator.Current.Get<IAddInTree>();
            

            if (Meta != null && Meta.AddIn == null)
                Meta.LoadAddIn();

        }

        public override object InitializeLifetimeService()
        {
            return null;
        }

        public void Start()
        {
            DoStart();
        }

        protected virtual void DoStart()
        {
            try
            {
                Listner.OnStarting( new ModuleEventArgs(this));

               

                if (Meta.AddIn != null && Meta.AddIn.Enabled)
                {

                    if (Meta.AddIn.Runtime.Imports.Count() > 0)
                    {
                        var classLoader = ServiceLocator.Current.Get<IClassLoader>();
                        foreach (var item in Meta.AddIn.Runtime.Imports)
                            classLoader.LoadAssembly(item);
                    }

                    AddInTree.Install(Meta.AddIn);

                    //if (Meta.AddIn.Runtime.Services != null)
                    //    ServiceRegistry.Load(Meta.AddIn.Runtime.Services, ClassLoader);
                    if (Meta.AddIn.Runtime.ExtensionPoints.Count() > 0)
                        ModuleActivatorProcessor = ServiceLocator.Current.Get<IModuleProvider>().CreateModuleActivatorProcessor(Meta);
                }

                if(ModuleActivatorProcessor == null)
                    ModuleActivatorProcessor = ServiceLocator.Current.Get<IModuleProvider>().CreateModuleActivatorProcessor(Meta);

                if (Meta.AddIn != null)
                    Meta.AddIn.Start();

                ModuleActivatorProcessor.Process();

               
                State = ModuleState.Actived;

                Listner.OnStarted( new ModuleEventArgs(this));
            }
            catch (Exception ex)
            {
                State = ModuleState.Installed;
                Listner.OnExcption(new ModuleEventArgs(this,ex));
            }
        }

        public void Stop()
        {
            DoStop();
        }

        protected virtual void DoStop()
        {
            try
            {
                if (Meta.AddIn != null)
                    Meta.AddIn.Enabled = false;

                Listner.OnStopping(new ModuleEventArgs(this));

                if (ModuleActivatorProcessor != null)
                    ModuleActivatorProcessor.Dispose();

                if (Meta.AddIn != null)
                    Meta.AddIn.Stop();
            }
            catch (Exception ex)
            {
                Listner.OnExcption(new ModuleEventArgs(this, ex));
            }

            this.State = ModuleState.Installed;
            Listner.OnStopped(new ModuleEventArgs(this));
        }

        public void Uninstall()
        {
            DoUninstall();
        }

        protected virtual void DoUninstall()
        {
            ServiceLocator.Current.Get<IModuleManager>().UninstallModule(Id);
            Meta = null;

            State = ModuleState.Uninstalled;
            Listner.OnUninstalled(new ModuleEventArgs(this));
        }

        public override string ToString()
        {
            return string.Format("id[{0}], name[{1}],state[{2}], addinName[{3}]", Id, Meta.Name, State, Meta.AddIn != null ? Meta.AddIn.Name : null);
        }
    }

    
}
